<?php 
/**
 * CMysqlTable class file.
 * 具体表数据记录类.
 * @author Huan Song <iphper@yeah.net>
 * @version $Id: CMysqlTable.php 1 2011-06-17 09:56:06Z huan.song $
 * @package system.db.mysql
 * @since 2.0
 */
class CMysqlTable extends CModel
{
	const BELONGS_TO = 'CBelongsToRelation';
	const HAS_ONE = 'CHasOneRelation';
	const HAS_MANY = 'CHasManyRelation';
	const MANY_MANY = 'CManyManyRelation';
	
	/**
     * @var class name => model
     */
	private static $_models = array();
	
	/**
     * @var class table => schema
     */
	private static $_schemas = array();
	
	/**
	 * @var CMysqlSchema 获取Mysql表的信息, 包含表的主键和外键, 列的情况.
	 */
	private $_dbSchema;
	
	/**
	 * @var CDbTableSchema 表的信息, 包含表的主键和外键, 列的情况.
	 */
	private $_schema;
	
	/**
	 * @var boolean 如果为true, 则是实例化的新表, 否则通过find等方法加载的表.
	 */
	private $_isNewRecord = false;
	
	/**
	 * @var array attribute name => attribute value 表中数据.
	 * 如果是实例化的新表, 则为空数组.
	 */
	private $_attributes = array();
	
	/**
	 * @var integer|string value 主键的值.
	 */
	private $_pk;
	
	/**
	 * @var array 所有列名, 用着查询的SQL语句.
	 */
	private $_selectFields = array();
	
	/**
	 * @var array 关系名 => Model对象.
	 */
	private $_related = array();
	
	/**
	 * 构造方法.
	 */
	public function __construct()
	{
		$this->setIsNewRecord(true);
		$this->_attributes = $this->getSchema()->attributeDefaults;
		$this->_init();
	}
	
	/**
     * 享元模式: 实例化Model类.
     * <pre>
     * class UsersModel extends CMysqlTable {}
     * $model = UsersModel::model();
     * $model = UsersModel::model()->find(1);
     * </pre>
     * @param $className 类名.
     * @return Object CMysqlTable.
	 */
	public static function model($className = __CLASS__)
	{
		if (!isset(self::$_models[$className]))
			self::$_models[$className] = new $className();
		
		return self::$_models[$className];
	}
	
	/**
	 * 查询一条记录.
	 * <pre>
	 * $model = UsersModel::model()->find(1);
	 * $model = UsersModel::model()->find(1, 'user_id');
	 * $model = UsersModel::model()->find('iphper', 'user_loginname');
	 * </pre>
	 * @param integer|string $value 字段值.
	 * @param string $field 字段名.
	 * @return Object|boolean CMysqlTable.
	 */
	public function find($value, $column = null)
	{
		if (null === $column)
			return $this->findByPk($value);
		
		$condition = $this->getDbSchema()->quoteColumnName($column) . ' = ?';
		return $this->findByCondition($condition, $value);
	}
	
	/**
	 * 通过条件查找多条记录.
	 * <pre>
	 * $models = UsersModel::model()->findAllByCondition('username LIKE ? OR email LIKE ?', array('username' => 'iphper', 'email' => 'iphper@yeah.net'));
	 * </pre>
	 * @param string $condition 条件.
	 * @param array $params 需要绑定的值.
	 * @return array (0 => CMysqlTable, 1 => CMysqlTable).
	 */
	public function findAll($condition = '1', $params = array())
	{
		return $this->findAllByCondition($condition, $params);
	}
	
	/**
	 * 通过主键查找一条记录.
	 * <pre>
	 * $model = UsersModel::model()->findByPk(1);
	 * </pre>
	 * @param integer|string $pk 主键值.
	 * @return Object|boolean CMysqlTable.
	 */
	public function findByPk($pk)
	{
		$condition = $this->_schema->rawPrimaryKey . ' = ?';
		return $this->findByCondition($condition, $pk);
	}
	
	/**
	 * 通过主键查找多条记录.
	 * <pre>
	 * $models = UsersModel::model()->findAllByPk(array(1, 2, 3));
	 * </pre>
	 * @param array 多个主键值.
	 * @return array (0 => CMysqlTable, 1 => CMysqlTable).
	 */
	public function findAllByPk(array $pks = array())
	{
		$len = count($pks);
		if ($len > 0)
		{
			$condition = $this->_schema->rawPrimaryKey . ' IN (' . substr(str_repeat('?, ', $len), 0, -2) . ')';
			return $this->findAllByCondition($condition, $pks);
		}
		
		return false;
	}
	
	/**
	 * 通过属性查找一条记录.
	 * <pre>
	 * $model = UsersModel::model()->findByAttributes(array('username' => 'iphper', 'email' => 'iphper@yeah.net'));
	 * </pre>
	 * @param array $attributes array ('username' => 'iphper', 'email' => 'iphper@yeah.net').
	 * @param array $params 需要绑定的值.
	 * @return Object|boolean CMysqlTable.
	 */
	public function findByAttributes($attributes)
	{
		$condition = implode(' = ? AND ', $this->getDbSchema()->quoteColumnNames(array_keys($attributes))) . ' = ?';
		return $this->findByCondition($condition, $attributes);
	}
	
	/**
	 * 通过属性查找多条记录.
	 * <pre>
	 * $models = UsersModel::model()->findAllByAttributes(array('username' => 'iphper', 'email' => 'iphper@yeah.net'));
	 * </pre>
	 * @param string $condition 条件.
	 * @param array $params 需要绑定的值.
	 * @return array (0 => CMysqlTable, 1 => CMysqlTable).
	 */
	public function findAllByAttributes($attributes)
	{
		$condition = implode(' = ? AND ', $this->getDbSchema()->quoteColumnNames(array_keys($attributes))) . ' = ?';
		return $this->findAllByCondition($condition, $attributes);
	}
	
	/**
	 * 通过条件查找一条记录.
	 * <pre>
	 * $model = UsersModel::model()->findByCondition('username = ? AND email = ?', array('username' => 'iphper', 'email' => 'iphper@yeah.net'));
	 * </pre>
	 * @param string $condition 条件.
	 * @param array $params 需要绑定的值.
	 * @return Object|boolean CMysqlTable.
	 */
	public function findByCondition($condition, $params = array())
	{
		if ($this->_selectFields !== array())
			$sql = 'SELECT ' . implode(', ', $this->getDbSchema()->quoteColumnNames($this->_selectFields)) . ' FROM ' . $this->_schema->rawName;
		else
			$sql = 'SELECT ' . implode(', ', $this->_schema->selectFields) . ' FROM ' . $this->_schema->rawName;
		
		$sql .= ' WHERE ' . $condition . ' LIMIT 1';
		$this->_selectFields = array();
		return $this->findBySql($sql, $params);
	}
	
	/**
	 * 通过条件查找多条记录.
	 * <pre>
	 * $models = UsersModel::model()->findAllByCondition('username LIKE ? OR email LIKE ?', array('username' => 'iphper', 'email' => 'iphper@yeah.net'));
	 * </pre>
	 * @param string $condition 条件.
	 * @param array $params 需要绑定的值.
	 * @return array (0 => CMysqlTable, 1 => CMysqlTable).
	 */
	public function findAllByCondition($condition, $params = array())
	{
		if ($this->_selectFields !== array())
			$sql = 'SELECT ' . implode(', ', $this->getDbSchema()->quoteColumnNames($this->_selectFields)) . ' FROM ' . $this->_schema->rawName;
		else 
			$sql = 'SELECT ' . implode(', ', $this->_schema->selectFields) . ' FROM ' . $this->_schema->rawName;
			
		$sql .= ' WHERE ' . $condition;
		$this->_selectFields = array();
		return $this->findAllBySql($sql, $params);
	}
	
	/**
     * 通过Sql语句, 返回一条结果集.
     * <pre>
	 * $model = UsersModel::model()->findBySql('SELECT * FROM ' . CDbConfig::getPrefix() . 'users WHERE username = ? AND email = ? LIMIT 1', array('username' => 'iphper', 'email' => 'iphper@yeah.net'));
	 * </pre>
	 * @param string $sql 需要执行的Sql语句.
	 * @param array|string|integer $params 需要绑定的参数.
     * @return Object|boolean CMysqlTable.
     */
	public function findBySql($sql, $params = array())
	{
		$row = $this->getDbStatement()->fetchAssocOneBySql($sql, $params);
		if ($row)
		{
			$this->_attributes = $row;
			$this->setPk();
			$this->setIsNewRecord(false);
			return $this;
		}
		
		return false;
	}
	
	/**
     * 通过Sql语句, 返回所有的结果集.
     * <pre>
	 * $models = UsersModel::model()->findAllBySql('SELECT * FROM ' . CDbConfig::getPrefix() . 'users WHERE username LIKE ? OR email LIKE ?', array('username' => 'iphper', 'email' => 'iphper@yeah.net'));
	 * </pre>
	 * @param string $sql 需要执行的Sql语句.
	 * @param array|string|integer $params 需要绑定的参数.
     * @return array (0 => CMysqlTable, 1 => CMysqlTable). 
     */
	public function findAllBySql($sql, $params = array())
	{
		$tables = array();
		$rows = $this->getDbStatement()->fetchAssocBySql($sql, $params);
		$name = $this->className();
		foreach ($rows as $row)
		{
			$table = new $name();
			$table->_attributes = $row;
			$table->setPk();
			$table->setIsNewRecord(false);
			$tables[] = $table;
		}
		
		return $tables;
	}
	
	/**
	 * 设置用着查询SQL语句的所有列名.
	 * @param array $fields 列名.
	 * <pre>
	 * $models = UsersModel::model()
	 * $models->setSelectFields(array('username', 'email'));
	 * $models->selectFields = array('username', 'email');
	 * </pre>
	 * @var array 所有列名, 用着查询的SQL语句.
	 */
	public function setSelectFields(array $fields = array())
	{
		if ($fields !== array())
			$this->_selectFields = $fields;
		
		return $this;
	}
	
	/**
	 * 通过属性统计记录数.
	 * <pre>
	 * $count = UsersModel::model()->countByAttributes(array('username' => 'iphper', 'email' => 'iphper@yeah.net'));
	 * </pre>
	 * @param array $attributes array ('username' => 'iphper', 'email' => 'iphper@yeah.net').
	 * @param array $params 需要绑定的值.
	 * @return integer.
	 */
	public function countByAttributes($attributes = array())
	{
		$condition = implode(' = ? AND ', $this->getDbSchema()->quoteColumnNames(array_keys($attributes))) . ' = ?';
		return $this->countByCondition($condition, $attributes);
	}
	
	/**
	 * 通过条件统计记录数.
	 * <pre>
	 * $count = UsersModel::model()->countByCondition('username LIKE ? OR email LIKE ?', array('username' => 'iphper', 'email' => 'iphper@yeah.net'));
	 * </pre>
	 * @param string $condition 条件.
	 * @param array $params 需要绑定的值.
	 * @return integer.
	 */
	public function countByCondition($condition, $params = array())
	{
		$sql = 'SELECT COUNT(' . $this->_schema->rawPrimaryKey . ') FROM ' . $this->_schema->rawName . ' WHERE ' . $condition;
		return $this->getDbStatement()->fetchColumnOneBySql($sql, $params);
	}
	
	/**
	 * 保存一条记录.
	 * <pre>
	 * $model = UsersModel::model();
	 * $model->attributes = $_POST;
	 * $model->save();
	 * 
	 * $model = UsersModel::model();
	 * $model->save(true, $_POST);
	 * 
	 * $model = UsersModel::model()->find(1);
	 * $model->attributes = $_POST;
	 * $model->save();
	 * </pre>
	 * @param boolean $runValidation 是否验证.
	 * @param array|null $attributes 需要保存的字段和属性. 如果为null, 则是$this->_attributes.
	 * @return boolean. 如果不是新实例或插入失败, 则返回false.
	 */
	public function save($runValidation = true, array $attributes = null)
	{
		if ($runValidation && $this->validate($attributes))
			return false;
		
		return $this->getIsNewRecord() ? $this->insert($attributes) : $this->update($attributes);
	}
	
	/**
	 * 添加一条记录.
	 * <pre>
	 * $model = UsersModel::model();
	 * $model->attributes = $_POST;
	 * $model->insert();
	 * 
	 * $model = UsersModel::model();
	 * $model->insert($_POST);
	 * </pre>
	 * @param array|null $attributes 需要插入表的字段和属性. 如果为null, 则是$this->_attributes.
	 * @return boolean. 如果不是新实例或插入失败, 则返回false.
	 */
    public function insert(array $attributes = null)
    {
    	if (!$this->getIsNewRecord())
    		throw new CModelException('CMysqlTable:insert cannot be inserted because it is not new');
    	
    	if (null !== $attributes)
	    	$this->setAttributes($attributes);
	    	
    	if ($this->preInsert())
    	{
	    	if (empty($this->_attributes))
	    		throw new CModelException('CMysqlTable:insert cannot be inserted because attributes is empty');
	    	
	    	if ($this->insertByAttributes($this->_attributes))
	    	{
	    		$this->_pk = $this->getDbDriver()->getLastInsertID();
	    		$this->setIsNewRecord(false);
	    		$this->postInsert();
	    		return true;
	    	}
    	}
    	
    	return false;
    }
    
	/**
	 * 添加一条记录.
	 * <pre>
	 * $model = UsersModel::model();
	 * $model->insert($_POST);
	 * </pre>
	 * @param array|null $attributes 需要插入表的字段和属性.
	 * @return boolean. 如果插入失败, 则返回false.
	 */
    public function insertByAttributes(array $attributes)
    {
    	$fields = implode(', ', $this->getDbSchema()->quoteColumnNames(array_keys($attributes)));
    	$values = substr(str_repeat('?, ', count($attributes)), 0, -2);
    	$sql = 'INSERT INTO ' . $this->_schema->rawName . ' (' . $fields . ') VALUES (' . $values . ')';
    	return $this->getDbStatement()->queryBySql($sql, $attributes);
    }
    
	/**
	 * 更新一条记录.
	 * <pre>
	 * $model = UsersModel::model()->find(1);
	 * $model->attributes = $_POST;
	 * $model->update();
	 * 
	 * $model = UsersModel::model()->find(1);
	 * $model->update($_POST);
	 * </pre>
	 * @param array|null $attributes 需要更新表的字段和属性. 如果为null, 则是$this->_attributes.
	 * @return boolean. 如果是新实例或更新失败, 则返回false.
	 */
    public function update(array $attributes = null)
    {
    	if ($this->getIsNewRecord())
    		throw new CModelException('CMysqlTable:update cannot be updated because it is new');
    	
    	if (null !== $attributes)
	    	$this->setAttributes($attributes);
	    
    	if ($this->preUpdate())
    	{
    		if (!$this->_pk)
    			throw new CModelException('CMysqlTable:update cannot be updated because pk is empty');
    		
	    	if (empty($this->_attributes))
	    		throw new CModelException('CMysqlTable:update cannot be updated because attributes is empty');
	    	
	    	if ($this->updateByPk($this->_pk, $this->_attributes))
	    	{
	    		$this->postUpdate();
	    		return true;
	    	}
    	}
    	
    	return false;
    }
    
    /**
	 * 通过主键更新一条记录.
	 * <pre>
	 * $bool = UsersModel::model()->updateByPk(1, $_POST);
	 * </pre>
	 * @param string|integer $pk 主键的值.
	 * @param array|null $attributes 需要更新表的字段和属性. 如果为null, 则是$this->_attributes.
	 * @return boolean. 如果更新失败, 则返回false.
	 */
    public function updateByPk($pk, $attributes)
    {
    	$dbStatement = $this->getDbStatement();
    	$fields = implode(' = ?, ', $this->getDbSchema()->quoteColumnNames(array_keys($attributes))) . ' = ?';
    	$dbStatement->sql = 'UPDATE ' . $this->_schema->rawName . ' SET ' . $fields . ' WHERE ' . $this->_schema->rawPrimaryKey . ' = ?';
    	$dbStatement->bindValues($attributes);
    	$dbStatement->bindValues(array($this->_schema->primaryKey => $pk));
    	return $dbStatement->queryBySql();
    }
    
	/**
	 * 删除一条记录.
	 * <pre>
	 * $model = UsersModel::model()->find(1);
	 * $model->delete();
	 * </pre>
	 * @return boolean. 如果是新实例或删除失败, 则返回false.
	 */
    public function delete()
    {
    	if ($this->getIsNewRecord())
    		throw new CModelException('CMysqlTable:delete cannot be deleted because it is new');
    	
    	if ($this->preDelete())
    	{
    		if (!$this->_pk)
    			throw new CModelException('CMysqlTable:delete cannot be updated because pk is empty');
    		
    		if ($this->deleteByPk($this->_pk))
    		{
    			$this->setIsNewRecord(true);
    			$this->_pk = null;
    			$this->_attributes = $this->_schema->attributeDefaults;
	    		$this->postDelete();
	    		return true;
    		}
    	}
    	
    	return false;
    }
    
    /**
	 * 通过主键值删除一条记录.
	 * <pre>
	 * $bool = UsersModel::model()->deleteByPk(1);
	 * </pre>
	 * @param string|integer $pk 主键的值.
	 * @return boolean. 如果删除失败, 则返回false.
	 */
    public function deleteByPk($pk)
    {
    	$sql = 'DELETE FROM ' . $this->_schema->rawName . ' WHERE ' . $this->_schema->rawPrimaryKey . ' = ?';
    	return $this->getDbStatement()->queryBySql($sql, $pk);
    }
	
    /**
	 * 通过关系名获取Model.
	 * <pre>
	 * $bool = UsersModel::model()->getRelated('profile');
	 * </pre>
	 * @param string $name 关系名.
	 * @return array|Object 所有关联的Model.
	 */
	public function getRelated($name, $refresh = false)
	{
		if (!$refresh && $this->hasRelated($name))
			return $this->_related[$name];
		
		if (!isset($this->relations) || !isset($this->relations[$name]))
			return null;
		
		$params = $this->relations[$name];
		$relation = CRelation::relation(array_shift($params));
		
		$this->_related[$name] = $relation->models($params, $this);
		return $this->_related[$name];
	}
	
	/**
	 * 判读是否设置Model关系.
	 * <pre>
	 * $bool = UsersModel::model()->hasRelated('profile');
	 * </pre>
	 * @param string $name 关系Model名.
	 * @return boolean.
	 */
	public function hasRelated($name)
	{
		return isset($this->_related[$name]) || array_key_exists($name, $this->_related);
	}
    
	/**
	 * 魔术方法: 返回已设置过的字段值或者一个受保护的属性值.
	 * <pre>
	 * $model = UsersModel::model()->find(1);
	 * echo $model->user_loginname;
	 * </pre>
	 * @param string $name 受保护的属性名.
	 * @return 受保护的属性值.
	 * @throws CException. 如果受保护的属性名不存在, 抛出CException.
	 * @see __set
	 */
    public function __get($name)
    {
        if (isset($this->_attributes[$name]))
     		return $this->_attributes[$name];
     	else if (isset($this->_schema->columns[$name]))
			return null;
		else if (null !== $this->getRelated($name))
			return $this->getRelated($name);
		
     	return parent::__get($name);
    }
    
    /**
	 * 魔术方法: 设置字段值或者一个受保护的属性值.
	 * <pre>
	 * $model = UsersModel::model()->find(1);
	 * $model->user_loginname = 'iphper';
	 * $model->save();
	 * </pre>
	 * @param string $name 受保护的属性名.
	 * @return 受保护的属性值.
	 * @throws CException. 如果受保护的属性名不存在, 抛出CException.
	 * @see __get
	 */
    public function __set($name, $value)
    {
    	if (isset($this->_schema->columns[$name]))
    		$this->_attributes[$name] = $value;
    	else
    		parent::__set($name, $value);
    }
	
	/**
	 * 魔术方法: 判断一个已字段是否设置值.
	 * <pre>
	 * $model = UsersModel::model()->find(1);
	 * var_dump(isset($model->user_loginname));
	 * </pre>
	 * @param string $name 字段名.
	 * @see __unset
	 */
    public function __isset($name)
    {
    	return isset($this->_attributes[$name]);
    }
    
    /**
	 * 魔术方法: 删除一个已设置的字段值.
	 * <pre>
	 * $model = UsersModel::model()->find(1);
	 * unset($model->user_loginname);
	 * </pre>
	 * @param string $name 字段名.
	 * @see __isset
	 */
    public function __unset($name)
    {
    	if (isset($this->_attributes[$name]))
     		unset($this->_attributes[$name]);
    }
    
    /**
	 * 魔术方法: 获取主键的值.
	 * <pre>
	 * $model = UsersModel::model()->find(1);
	 * echo $model->getPk();
	 * echo $model->pk;
	 * </pre>
	 * @see setPk
	 */
    public function getPk()
    {
    	return $this->_pk;
    }
    
    /**
	 * 魔术方法: 设置主键的值.
	 * <pre>
	 * $model = UsersModel::model();
	 * $model->setPk();
	 * $model->setPk(1);
	 * $model->pk = 1;
	 * </pre>
	 * @param string|integer|null $value 主键的值.
	 * @see getPk
	 */
    public function setPk($value = null)
    {
    	if (null === $value && isset($this->_attributes[$this->_schema->primaryKey]))
    		$value = $this->_attributes[$this->_schema->primaryKey];
    		
    	$this->_pk = $value;
    }
    
   	/**
   	 * 获取所有的字段值.
   	 * <pre>
	 * $model = UsersModel::model();
	 * $attributes = $model->getAttributes();
	 * $attributes = $model->attributes;
	 * </pre>
	 * @return array 所有字段值.
	 * @see setAttributes
	 */
    public function getAttributes()
    {
    	return $this->_attributes;
    }
    
    /**
	 * 设置所有的字段值.
	 * <pre>
	 * $model = UsersModel::model();
	 * $model->setAttributes($_POST);
	 * $model->attributes = $_POST;
	 * </pre>
	 * @param array 所有字段值.
	 * @see getAttributes
	 */
    public function setAttributes(array $attributes = array())
    {
    	foreach ($attributes as $name => $value)
    	{
	    	if (isset($this->_schema->columns[$name]))
	    		$this->_attributes[$name] = $value;
    	}
    }
	
	/**
	 * 获取模型类名.
     * @return 模型类名.
	 */
	protected function className()
	{
		return get_class($this);
	}
	
	/**
	 * 获取表名.
     * @return 表名.
	 */
	protected function tableName()
	{
		return CDbConfig::getPrefix() . strtolower(substr($this->className(), 0, -strlen(CModelConfig::getModelKey())));
	}
	
	/**
	 * 获取表的信息, 包含表的主键和外键, 列的情况.
	 * <pre>
	 * $model = UsersModel::model();
	 * $dbSchema = $model->getDbSchema();
	 * $dbSchema = $model->dbSchema;
	 * </pre>
     * @return Object CDbSchema 表的信息, 包含表的主键和外键, 列的情况.
	 */
	public function getDbSchema()
	{
		if (null === $this->_dbSchema)
		{
			$dbSchema = 'C' . ucfirst(CDbConfig::getDbType()) . 'Schema';
			$this->_dbSchema = new $dbSchema();
		}
		
		return $this->_dbSchema;
	}
	
	/**
	 * 获取表的信息, 包含表的主键和外键, 列的情况.
	 * <pre>
	 * $model = UsersModel::model();
	 * $schema = $model->getSchema();
	 * $schema = $model->schema;
	 * </pre>
     * @return Object CMysqlTableSchema 表的信息, 包含表的主键和外键, 列的情况.
	 */
	public function getSchema()
	{
		if (null === $this->_schema)
		{
			$tableName = str_replace('#@_', CDbConfig::getPrefix(), $this->tableName());
			if (!isset(self::$_schemas[$tableName]))
				self::$_schemas[$tableName] = $this->getDbSchema()->loadTable($tableName);
			
			$this->_schema = self::$_schemas[$tableName];
		}
		
		return $this->_schema;
	}
	
	/**
	 * 获取是否是实例化的新表, 如果为true, 则是实例化的新表, 否则通过find等方法加载的表.
	 * <pre>
	 * $model = UsersModel::model();
	 * $bool = $model->getIsNewRecord();
	 * $bool = $model->isNewRecord;
	 * </pre>
	 * @return boolean.
	 * @see setIsNewRecord
	 */
    public function getIsNewRecord()
    {
    	return $this->_isNewRecord;
    }
    
    /**
     * 设置是否是实例化的新表, 如果为true, 则是实例化的新表, 否则通过find等方法加载的表.
     * <pre>
	 * $model = UsersModel::model();
	 * $model->setIsNewRecord(true);
	 * $model->isNewRecord = false;
	 * </pre>
     * @param boolean.
     * @see getIsNewRecord
	 */
    public function setIsNewRecord($value)
    {
    	$this->_isNewRecord = (boolean) $value;
    }
    
	/**
	 * 子类构造方法: 为了防止构造方法被重写, 子类可以调用此方法作为构造方法.
	 */
	protected function _init()
	{
	}
	
	protected function preInsert()
    {
    	return true;
    }
    
    protected function postInsert()
    {
    }
    
    protected function preUpdate()
    {
    	return true;
    }
    
    protected function postUpdate()
    {
    }
    
    protected function preDelete()
    {
    	return true;
    }
    
    protected function postDelete()
    {
    }
}

/**
 * CMysqlTable class file.
 * Model关系父类.
 * @author Huan Song <iphper@yeah.net>
 * @version $Id: CMysqlTable.php 1 2011-06-17 09:56:06Z huan.song $
 * @package system.db.mysql
 * @since 2.0
 */
class CRelation
{
	private static $_relations = array();
	
	public static function relation($className)
	{
		if (!isset(self::$_relations[$className]))
			self::$_relations[$className] = new $className();
		
		return self::$_relations[$className];
	}
}

/**
 * CMysqlTable class file.
 * Model关系类, 属于关系.
 * @author Huan Song <iphper@yeah.net>
 * @version $Id: CMysqlTable.php 1 2011-06-17 09:56:06Z huan.song $
 * @package system.db.mysql
 * @since 2.0
 */
class CBelongsToRelation extends CRelation
{
	public function models($params, $model)
	{
		$className = ucfirst(strtolower($params[0])) . CModelConfig::getModelKey();
		$class = new $className();
		$class->findByAttributes(array($params[1] => $model->$params[1]));
		return $class;
	}
}

/**
 * CMysqlTable class file.
 * Model关系类, 一对一关系.
 * @author Huan Song <iphper@yeah.net>
 * @version $Id: CMysqlTable.php 1 2011-06-17 09:56:06Z huan.song $
 * @package system.db.mysql
 * @since 2.0
 */
class CHasOneRelation extends CRelation
{
}

/**
 * CMysqlTable class file.
 * Model关系类, 一对多关系.
 * @author Huan Song <iphper@yeah.net>
 * @version $Id: CMysqlTable.php 1 2011-06-17 09:56:06Z huan.song $
 * @package system.db.mysql
 * @since 2.0
 */
class CHasManyRelation extends CRelation
{
	public function models($params, $model)
	{
		$className = ucfirst(strtolower($params[0])) . CModelConfig::getModelKey();
		$class = new $className();
		return $class->findAllByAttributes(array($params[1] => $model->$params[1]));
	}
}

/**
 * CMysqlTable class file.
 * Model关系类, 多对多关系.
 * @author Huan Song <iphper@yeah.net>
 * @version $Id: CMysqlTable.php 1 2011-06-17 09:56:06Z huan.song $
 * @package system.db.mysql
 * @since 2.0
 */
class CManyManyRelation extends CRelation
{
}
